/**
 * @author: phutp@younetco.com
 * @version: 0.1
 */
var Common = {};

/*{ Begin Form---------------------------------------*/
;
(function(){
    /*
     * Preload image
     * input: array source of image
     * output: all image was loaded
     */
    $.fn.preload = function() {
        this.each(function(){
            $('<img />').attr('src', this);
        });
    };

	jQuery.fn.ymFormHandle = function(options) {
		if (!this.length) {
			log('Could not found the matched element!');
			return this;
		}
		var settings = {
			usingSimplePrize : false,
			maxNumberPhase : 3
		};
		function init(options)
		{
			var form = this;
			$(this).find('#language-label').before('<dt id="appearance">Appearance </dt><dd id="appearance-dd"><hr /></dd>');
            $(this).find('#unit_code-label').before('<dt id="purchase_settings">Purchase settings </dt><dd id="purchase_settings-dd"><hr /></dd>');
			$('.tooltip_label', this).tipsy({html:true,gravity: $.fn.tipsy.autoNS});

			$('#cancel',this).click(function(e){
				e.preventDefault();
				location.href = options['cancel-url'];
			});

			$(this).delegate('.system_category','change',function(e){
				if( this.value )
				{
					$(this).parent().nextAll().remove();
					$.get(
						options['get-system-categories-url'],
						{
							'id_parent' : $(this).val()
						},
						$.proxy(function(data){
							if( data && !(data instanceof Array) )
							{
								var category = [];
								category.push('<dd>');
								category.push('<select class="system_category" name="id_system_category[system_category_'+(new Date().getTime())+']">');
								category.push('<option value="">'+options['label']['select']+'</option>');
								for(id in data)
								{
									category.push('<option value="'+id+'">'+data[id]+'</option>');
								}
								category.push('</select>');
								category.push('</dd>');
								$(this).parent().after(category.join(''));
							}
						},this),
						'json'
					)
				}
				else
				{
					$(this).parent().nextAll().remove();
				}
			});

			$(this).find('textarea').each(function(){
				return;
				var readonly = this.disabled || this.readonly || false;
				$(this).tinymce({
					// Location of TinyMCE script
					width		: '496',
					script_url	: options['tiny_mce_url'],

					relative_urls : false,

					mode			: "textareas",
					theme			: 'advanced',
					skin			: "s7n",
					plugins			: "safari",
					entity_encoding : "raw",
					convert_urls	: false,
					readonly		: readonly,
					valid_elements	: "*[*]",

					// Theme options
					theme_advanced_buttons1 : "formatselect,fontselect,|,pagebreak,bold,italic,removeformat,|,bullist,numlist,blockquote,|,justifyleft,justifycenter,justifyright,|,code",
					theme_advanced_buttons2 : "",
					theme_advanced_buttons3 : "",

					theme_advanced_toolbar_location		: "top",
					theme_advanced_toolbar_align		: "left",
					theme_advanced_statusbar_location	: "none",
					theme_advanced_resizing				: false,
					theme_advanced_blockformats			: 'p,address,h1,h2,h3,h4,h5,h6',

					setup : function(ed) {
					}
				});
			});


			$(this).find(':input').change(function(){
				window.isChanged = true;
			});

			$(".btn_delete").click(function(e){
				$img = $(this).parent().find('img');
				if( !$img.data('originalImg') )
				{
					$img.data('originalImg',$img.attr('src'))
				}
				if( $(this).text() === 'delete' )
				{
					$(this).parent().find(':hidden').val(1);
					$img.attr('src','img/image_not_available.gif');
					$(this).text('undelete');
				}
				else
				{
					$(this).parent().find(':hidden').val(0);
					$img.attr('src',$img.data('originalImg'));
					$(this).text('delete');
				}
			});
			$(".inline_delete").click(function(e){
				if ($(this).text() === 'delete')
				{
					$(this).parents('dd').find(':hidden').val(1);
					$(this).parents('dd').find('.text').hide();
					$(this).text('undelete');
				}
				else
				{
					$(this).parents('dd').find(':hidden').val(0);
					$(this).parents('dd').find('.text').show();
					$(this).text('delete');
				}
			});

			$('input[name="store_layout[]"]').change(function(){
				var value = $(this).val();
				if(this.checked)
				{
					$('#default_layout').find('option[value="'+value+'"]').attr('disabled',false);
					$('#default_layout').find('option[value="'+value+'"]').css('color','#000000');
				}
				else
				{
					if(value == $('#default_layout').val())
					{
						$('#default_layout').val(0);
					}

					$('#default_layout').find('option[value="'+value+'"]').attr('disabled','disabled');
					$('#default_layout').find('option[value="'+value+'"]').css('color','#666666');
				}
			});

			$(this).submit(function() {});
		}
		options = $.extend( settings, options );
		return this.each(function() {
			if ( options ) {
				init.call(this,options);
			}
		});

	}

	jQuery.fn.ymFormCategory = function(options) {
		if (!this.length) {
			log('Could not found the matched element!');
			return this;
		}
		var settings = {
		};
		function init(options)
		{
			$(this).find('.add').click(function(e){
				//Prevent submit from button
				e.preventDefault();
				var template	= options['create-form-template'];
				var obj			= this;
				Social.getDialog().create({
					title:options.label['title-create'],
					content: template,
					closeIcon: true,
					onClose: function() {
						$(this).dialog("close");
					},
					onOk: function() {
						$(this).find('form').submit();
						$(this).dialog("close");
					},
					visible: true,
					init: function(){
						$(this).find('#selCategoryIdParent').html($(obj).data('name'));
						$(this).find('#hdnCategoryId').val($(obj).data('id-parent'));
						$('#txtCategoryName', this).focus();
					}
				});
			});
			$(this).find('.delete').click(function(e){
				e.preventDefault();
				var template	= options['confirm-delete-template'];
				var	obj			= this;
				Social.getDialog().create({
					title: options.label['title-confirm'],
					content: template,
					closeIcon: true,
					onClose: function() {
						$(this).dialog("close");
					},
					onOk: function(){
						var idCategory	= $(obj).data('id-category');
						var deleteUrl	= options['delete-url'];
						location.href	= deleteUrl+'/id_category/'+idCategory;
						$(this).dialog("close");
					},
					visible: true,
					init: function()
					{
						$(this).find('#delete-category-name').html($(obj).data('name'));						
					}
				});
			});
			$(this).find('.edit').click(function(e){
				//Prevent submit from button
				e.preventDefault();
				var template	= options['update-form-template'];
				var obj			= this;				
				Social.getDialog().create({
					title: options.label['title-edit'],
					content: template,
					closeIcon: true,
					onClose: function() {
						$(this).dialog("close");
					},
					onOk:function(){
						$(this).find('form').submit();
						$(this).dialog("close");
					},
					visible: true,
					init: function(){
						var idCategory = $(obj).data('id-category');
						$(this).find('#hdnCategoryId').val(idCategory);
						$(this).find('#txtCategoryName').val(htmlspecialchars_decode($(obj).data('name')));
						$(this).find('#selCategoryIdParent').html($(obj).data('parent-name'));
						$('#txtCategoryName', this).focus();
					}
				});
			});
			$(this).find("#btn-create").click(function(e){
				//Prevent submit from button
				e.preventDefault();
				var template	= options['create-form-template'];				
				var	obj			= this;
				Social.getDialog().create({
					title: options.label['title-create'],
					content: template,
					closeIcon: true,
					onClose: function() {
						$(this).dialog("close");
					},
					onOk:function(){
						$(this).find('form').submit();
						$(this).dialog("close");
					},
					visible: true,
					init: function()
					{
						$(this).find('#selCategoryIdParent').html(options['label']['category-root']);
						$('#txtCategoryName', this).focus();
					}
				});
			});
			$('.list-categories',this).nestedSortable({
				handle: 'table',
				items: 'li',
				toleranceElement: '> table',
				placeholder: 'placeholder',
				forcePlaceholderSize: true,
				helper:	'clone',
				stop : function(event, ui) {
					var data = {
						above:	0,
						to:		0,
						id:		0
					};
					var $parent = ui.item.closest('ol').parent('li').find('.sm_link.edit');
					if( $parent.data('id-category') )
					{
						data['to'] = $parent.data('id-category');
					}
					var $next	= ui.item.next().find('.sm_link.edit');

					if( $next.data('id-category') )
					{
						data['above'] = $next.data('id-category');
					}
					if( ui.item.find('.sm_link.edit') )
					{
						data['id'] = ui.item.find('.sm_link.edit').data('id-category');
					}
					//Disable Sortable - Pending util update successfully
					$('.list-categories').sortable('disable');
					if( $('.ms_message').length == 0 )
					{
						$('.list-categories').before('<div class="ms_message"></div>');
					}
					$('.ms_message').text(options['label']['sortable-waiting']);
					$.get(
						options['move-url'],
						data,
						function(result)
						{
							//Enable Sortable
							$('.ms_message').text(options['label']['sortable-successful']);
							$('.list-categories').sortable('enable');
						}
					);
				}
			});
		}
		options = $.extend( settings, options );
		return this.each(function() {
			if ( options ) {
				init.call(this,options);
			}
		});

	}

	jQuery.fn.ymFormProduct = function(options) {
		if (!this.length) {
			log('Could not found the matched element!');
			return this;
		}
		var settings = {
		};
		function init(options)
		{
			$('.tooltip_label', this).tipsy({html:true,gravity: $.fn.tipsy.autoNS});
			$('#cancel',this).click(function(e){
				e.preventDefault();
				location.href = options['cancel-url'];
			});
			$(this).find(".helper-image").not(':first').append('<div class="group-control">&nbsp;</div>');
			$(this).delegate('.group-control', 'click', function(e){
				$(this).closest('.helper-image').next().remove();
				$(this).closest('.helper-image').next().remove();
				$(this).closest('.helper-image').remove();
			});
			$(this).find('#description').each(function(){
				return;
				var readonly = this.disabled || this.readonly || false;
				$(this).tinymce({
					// Location of TinyMCE script
					width		: '496',
					script_url	: options['tiny_mce_url'],

					mode			: "textareas",
					theme			: 'advanced',
					skin			: "s7n",
					plugins			: "safari",
					entity_encoding : "raw",
					convert_urls	: false,
					readonly		: readonly,
					valid_elements	: "*[*]",

					// Theme options
					theme_advanced_buttons1 : "formatselect,fontselect,|,pagebreak,bold,italic,removeformat,|,bullist,numlist,blockquote,|,justifyleft,justifycenter,justifyright,|,code",
					theme_advanced_buttons2 : "",
					theme_advanced_buttons3 : "",

					theme_advanced_toolbar_location		: "top",
					theme_advanced_toolbar_align		: "left",
					theme_advanced_statusbar_location	: "none",
					theme_advanced_resizing				: false,
					theme_advanced_blockformats			: 'p,address,h1,h2,h3,h4,h5,h6',

					setup : function(ed) {
					}
				});
			});
			$('#'+'images-element .hr:last').parent().append('<a style="border-top:1px dashed #CCCCCC; width:100%;" href="javascript:void(0);" type="button" class="btn_add_image_description">'+options['label']['add-more']+'</a>');
			$(this).delegate('.btn_add_image_description','click',function(e){
				e.preventDefault();
				var template = options['image-description-template'].replace(new RegExp('(\\${id})', 'g'), (new Date()).getTime());
				$(this).before(template);
			});
			$(this).delegate('.system_category','change',function(e){
				if( this.value )
				{
					$(this).parent().nextAll().remove();
					$.get(
						options['get-system-categories-url'],
						{
							'id_parent' : $(this).val()
						},
						$.proxy(function(data){
							if( data && !(data instanceof Array) )
							{
								var category = [];
								category.push('<dd>');
								category.push('<select class="system_category" name="id_system_category[system_category_'+(new Date().getTime())+']">');
								category.push('<option value="">'+options['label']['select']+'</option>');
								for(id in data)
								{
									category.push('<option value="'+id+'">'+data[id]+'</option>');
								}
								category.push('</select>');
								category.push('</dd>');
								$(this).parent().after(category.join(''));
							}
						},this),
						'json'
					)
				}
				else
				{
					$(this).parent().nextAll().remove();
				}
			});
			$(".custom_category").each(function(){
				$(this).after('<a href="javascript:void(0)" class="add_new_category">'+options['label']['add-new-category']+'</a>');
			});
			$(this).delegate('.add_new_category', 'click', function(e){
				var $select		= $(this).prev();
				var idParent	= $select.data('id-parent');
				var parentName	= $select.data('parent-name');
				Social.getDialog().create({
					title: options.label['title-category-create'],
					content: options['create-form-template'],
					closeIcon: true,
					onClose: function() {
						$(this).dialog("close");
					},
					onOk: function(){
						var form = $(this).find('form').get(0);
						var arrFormValues = $(form).serializeArray();
						var arrValues = {};
						for(var i = 0; i < arrFormValues.length; i++)
						{
							arrValues[arrFormValues[i].name] = arrFormValues[i].value;
						}
						$.post(
							form.action,
							arrValues,
							$.proxy(function(data){
								$(this).append('<option value="'+data['id']+'">'+data['name']+'</option>');
								$(this).val(data['id']);
								$(this).change();
							},$select[0]),
							'json'
						);
						$(this).dialog("close");
					},
					visible: true,
					init: function()
					{
						$(this).find('#selCategoryIdParent').html(parentName);
						$(this).find('#hdnCategoryId').val(idParent);
						$('#txtCategoryName',this).focus();
					},
					open: function(event, ui)
					{
						$('#txtCategoryName').keydown($.proxy(function(e){
							var code = e.which || e.keyCode;							
							if( code == 13 )
							{
								var buttons = $(this).dialog('option','buttons');
								buttons['Ok'].apply(this);
								return false;
							}
							return true;
						},this));
					}
				});
			});
			$(this).on('change', '.custom_category', function(e){
				if( this.value )
				{
					$(this).parent().nextAll().remove();
					$.get(
						options['get-custom-categories-url'],
						{
							'id_parent' : $(this).val()
						},
						$.proxy(function(data){
							$(this).parent().nextAll().remove();
							if( $(this).val() )
							{
								var category = [];
								category.push('<dd>');
								category.push('<select class="custom_category" ');
								category.push('name="id_custom_category[custom_category_'+(new Date().getTime())+']" ');
								category.push('data-id-parent="'+$(this).val()+'" ');
								category.push('data-parent-name="'+$(this).find('option:selected').text()+'" ');
								category.push('>');
								category.push('<option value="">'+options['label']['select']+'</option>')
								for(id in data)
								{
									category.push('<option value="'+id+'">'+data[id]+'</option>')
								}
								category.push('</select>');
								category.push('<a href="javascript:void(0)" class="add_new_category">'+options['label']['add-new-category']+'</a>');
								category.push('</dd>');
								$(this).parent().after(category.join(''));
							}
						},this),
						'json'
					);
				}
				else
				{
					$(this).parent().nextAll().remove();
				}
			});
		}
		options = $.extend( settings, options );
		return this.each(function() {
			if ( options ) {
				init.call(this,options);
			}
		});

	}

	jQuery.fn.ymProductImage = function(options) {
		if (!this.length) {
			log('Could not found the matched element!');
			return this;
		}
		var settings = {
		};
		function init(options)
		{
			$(this).hover(
				function(){
					var $img = $(this).find('img');
					var $div = $('.' + options.div);
					var topDiff = 20;
					var leftDiff = 20;

					$div.css('top', ($img.offset().top - topDiff));
					$div.css('left', ($img.offset().left - leftDiff));
					$div.find('img').attr('src', $img.attr('src'));
					$div.show();
				}
			);

		}
		options = $.extend( settings, options );
		return this.each(function() {
			if ( options ) {
				init.call(this,options);
			}
			$('.' + options.div).unbind().hover(
				function()
				{
				},
				function()
				{
					$(this).hide();
				}
			);
		});

	}
	jQuery.fn.ymProductItem = function(options) {
		if (!this.length) {
			log('Could not found the matched element!');
			return this;
		}
		var settings = {
				'hover' : true,
				'gravity' : 's'
		};
		function init(options)
		{
			$(this).find('a.fb_button_share_custom').tipsy({gravity: options['gravity']});
			$(this).find('a.fb_button_recommend').tipsy({gravity: options['gravity']});

			if (options['hover'])
			{
				$(this).hover(
					function(){
						$(this).find('.recommend_back').css('height', 34);
					},
					function(){
						$(this).find('.recommend_back').css('height', 0);
					}
				);
			}

			$(this).find('.fb_button_recommend').click(function(){
				var data = new Object();
				data.id_product = $(this).attr('data-id_product');
				data.id_page = $(this).attr('data-id_page');
				var message = $(this).attr('data-message');

				sendAppRequests(message, data);
			});
		}
		options = $.extend( settings, options );
		return this.each(function() {
			init.call(this,options);
		});

	}
	jQuery.fn.ymProductShareUrl = function(options) {

		if (!this.length) {
			log('Could not found the matched element!');
			return this;
		}
		var settings = {

		};
		function init(options)
		{
			var $div = $(this);
			var $url_pannel = $div.find('.url_pannel');
			var $input = $div.find('input');
			var $short = $long = false;

			$input.click(function(){
				$(this).select();
			})
			$('.url_pannel').click(function(e){
				return false;
			});

			$('body').click(function(e){

				$div.find('.url_pannel').hide();
				if( $(e.target).is('.short_url') )
				{
					if( !$short )
					{
						$url_pannel.show();
						$input.val(options['short-url']).focus().select();
						$long = false;
					}
					$short = !$short;
					e.preventDefault();
				}
				else if( $(e.target).is('.long_url') )
				{
					if( !$long )
					{
						$url_pannel.show();
						$input.val(options['long-url']).focus().select();
						$short = false;
					}
					$long = !$long;
					e.preventDefault();
				} else
				{
					$short = $long = false;
				}
			});
		}
		options = $.extend( settings, options );
		return this.each(function() {
			init.call(this,options);
		});

	}
	function log(obj) {
		if( window.console && console.log ) console.log(obj) ;
	}
})(jQuery);
/*------------------------------------------}End Form*/
function selectTab(id)
{
	$('#' + id).addClass('active');
}

function addTab(caption, url)
{
	if (caption.length > 30)
	{
		caption = caption.substr(0, 30) + "...";
	}
	$('#tabs').find("li").removeClass('active');
	$('#tabs').append('<li class="active"><a href="'+url+'">'+caption+'</a></li>');
}
function validateEmail(email) {
    var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return re.test(email);
}

function setrawcookie (name, value, expires, path, domain, secure) {
    if (typeof expires === 'string' && (/^\d+$/).test(expires)) {
        expires = parseInt(expires, 10);
    }

    if (expires instanceof Date) {
        expires = expires.toGMTString();
    } else if (typeof(expires) === 'number') {
        expires = (new Date(expires * 1e3)).toGMTString();
    }

    var r = [name + '=' + value],
        s = {},
        i = '';
    s = {
        expires: expires,
        path: path,
        domain: domain
    };
    for (i in s) {
        if (s.hasOwnProperty(i)) { // Exclude items on Object.prototype
            s[i] && r.push(i + '=' + s[i]);
        }
    }

    return secure && r.push('secure'), this.window.document.cookie = r.join(";"), true;
}
function setcookie (name, value, expires, path, domain, secure) {
    return setrawcookie(name, encodeURIComponent(value), expires, path, domain, secure);
}
function getcookie(c_name)
{
	var i,x,y,ARRcookies=document.cookie.split(";");
	for (i=0;i<ARRcookies.length;i++)
	{
		x=ARRcookies[i].substr(0,ARRcookies[i].indexOf("="));
		y=ARRcookies[i].substr(ARRcookies[i].indexOf("=")+1);
		x=x.replace(/^\s+|\s+$/g,"");
		if (x==c_name)
		{
			return unescape(y);
		}
	}
	return false;
}

function htmlspecialchars_decode (string, quote_style) {
    var optTemp = 0,
        i = 0,
        noquotes = false;
    if (typeof quote_style === 'undefined') {
        quote_style = 2;
    }
    string = string.toString().replace(/&lt;/g, '<').replace(/&gt;/g, '>');
    var OPTS = {
        'ENT_NOQUOTES': 0,
        'ENT_HTML_QUOTE_SINGLE': 1,
        'ENT_HTML_QUOTE_DOUBLE': 2,
        'ENT_COMPAT': 2,
        'ENT_QUOTES': 3,
        'ENT_IGNORE': 4
    };
    if (quote_style === 0) {
        noquotes = true;
    }
    if (typeof quote_style !== 'number') { // Allow for a single string or an array of string flags
        quote_style = [].concat(quote_style);
        for (i = 0; i < quote_style.length; i++) {
            // Resolve string input to bitwise e.g. 'PATHINFO_EXTENSION' becomes 4
            if (OPTS[quote_style[i]] === 0) {
                noquotes = true;
            } else if (OPTS[quote_style[i]]) {
                optTemp = optTemp | OPTS[quote_style[i]];
            }
        }
        quote_style = optTemp;
    }
    if (quote_style & OPTS.ENT_HTML_QUOTE_SINGLE) {
        string = string.replace(/&#0*39;/g, "'"); // PHP doesn't currently escape if more than one 0, but it should
        // string = string.replace(/&apos;|&#x0*27;/g, "'"); // This would also be useful here, but not a part of PHP
    }
    if (!noquotes) {
        string = string.replace(/&quot;/g, '"');
    }
    // Put this in last place to avoid escape being double-decoded
    string = string.replace(/&amp;/g, '&');

    return string;
}

function clearFormDataInBackend()
{
    oFormObject = document.forms['form_search'];
    oFormObject.elements["keyword"].value = 'keyword';
    oFormObject.elements["category"].value = '0';
    oFormObject.elements["status"].value = '';
}
function clearFormDataInFronend()
{
    oFormObject = document.forms['form_search'];
    oFormObject.elements["keyword"].value = 'keyword';
    oFormObject.elements["category"].value = '0';
    return false;
}
;(function($) {

$.fn.extend({
	simulate: function(type, options) {
		return this.each(function() {
			var opt = $.extend({}, $.simulate.defaults, options || {});
			new $.simulate(this, type, opt);
		});
	}
});

$.simulate = function(el, type, options) {
	this.target = el;
	this.options = options;

	if (/^drag$/.test(type)) {
		this[type].apply(this, [this.target, options]);
	} else {
		this.simulateEvent(el, type, options);
	}
}

$.extend($.simulate.prototype, {
	simulateEvent: function(el, type, options) {
		var evt = this.createEvent(type, options);
		this.dispatchEvent(el, type, evt, options);
		return evt;
	},
	createEvent: function(type, options) {
		if (/^mouse(over|out|down|up|move)|(dbl)?click$/.test(type)) {
			return this.mouseEvent(type, options);
		} else if (/^key(up|down|press)$/.test(type)) {
			return this.keyboardEvent(type, options);
		}
	},
	mouseEvent: function(type, options) {
		var evt;
		var e = $.extend({
			bubbles: true, cancelable: (type != "mousemove"), view: window, detail: 0,
			screenX: 0, screenY: 0, clientX: 0, clientY: 0,
			ctrlKey: false, altKey: false, shiftKey: false, metaKey: false,
			button: 0, relatedTarget: undefined
		}, options);

		var relatedTarget = $(e.relatedTarget)[0];

		if ($.isFunction(document.createEvent)) {
			evt = document.createEvent("MouseEvents");
			evt.initMouseEvent(type, e.bubbles, e.cancelable, e.view, e.detail,
				e.screenX, e.screenY, e.clientX, e.clientY,
				e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
				e.button, e.relatedTarget || document.body.parentNode);
		} else if (document.createEventObject) {
			evt = document.createEventObject();
			$.extend(evt, e);
			evt.button = {0:1, 1:4, 2:2}[evt.button] || evt.button;
		}
		return evt;
	},
	keyboardEvent: function(type, options) {
		var evt;

		var e = $.extend({bubbles: true, cancelable: true, view: window,
			ctrlKey: false, altKey: false, shiftKey: false, metaKey: false,
			keyCode: 0, charCode: 0
		}, options);

		if ($.isFunction(document.createEvent)) {
			try {
				evt = document.createEvent("KeyEvents");
				evt.initKeyEvent(type, e.bubbles, e.cancelable, e.view,
					e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
					e.keyCode, e.charCode);
			} catch(err) {
				evt = document.createEvent("Events");
				evt.initEvent(type, e.bubbles, e.cancelable);
				$.extend(evt, {view: e.view,
					ctrlKey: e.ctrlKey, altKey: e.altKey, shiftKey: e.shiftKey, metaKey: e.metaKey,
					keyCode: e.keyCode, charCode: e.charCode
				});
			}
		} else if (document.createEventObject) {
			evt = document.createEventObject();
			$.extend(evt, e);
		}
		if ($.browser.msie || $.browser.opera) {
			evt.keyCode = (e.charCode > 0) ? e.charCode : e.keyCode;
			evt.charCode = undefined;
		}
		return evt;
	},

	dispatchEvent: function(el, type, evt) {
		if (el.dispatchEvent) {
			el.dispatchEvent(evt);
		} else if (el.fireEvent) {
			el.fireEvent('on' + type, evt);
		}
		return evt;
	},

	drag: function(el) {
		var self = this, center = this.findCenter(this.target),
			options = this.options,	x = Math.floor(center.x), y = Math.floor(center.y),
			dx = options.dx || 0, dy = options.dy || 0, target = this.target;
		var coord = {clientX: x, clientY: y};
		this.simulateEvent(target, "mousedown", coord);
		coord = {clientX: x + 1, clientY: y + 1};
		this.simulateEvent(document, "mousemove", coord);
		coord = {clientX: x + dx, clientY: y + dy};
		this.simulateEvent(document, "mousemove", coord);
		this.simulateEvent(document, "mousemove", coord);
		this.simulateEvent(target, "mouseup", coord);
	},
	findCenter: function(el) {
		var el = $(this.target), o = el.offset();
		return {
			x: o.left + el.outerWidth() / 2,
			y: o.top + el.outerHeight() / 2
		};
	}
});

$.extend($.simulate, {
	defaults: {
		speed: 'sync'
	},
	VK_TAB: 9,
	VK_ENTER: 13,
	VK_ESC: 27,
	VK_PGUP: 33,
	VK_PGDN: 34,
	VK_END: 35,
	VK_HOME: 36,
	VK_LEFT: 37,
	VK_UP: 38,
	VK_RIGHT: 39,
	VK_DOWN: 40
});

})(jQuery);


/*
 * jQuery UI Nested Sortable
 * v 1.3.5 / 21 jun 2012
 * http://mjsarfatti.com/code/nestedSortable
 *
 * Depends on:
 *	 jquery.ui.sortable.js 1.8+
 *
 * Copyright (c) 2010-2012 Manuele J Sarfatti
 * Licensed under the MIT License
 * http://www.opensource.org/licenses/mit-license.php
 */

(function($) {

	$.widget("mjs.nestedSortable", $.extend({}, $.ui.sortable.prototype, {

		options: {
			tabSize: 20,
			disableNesting: 'mjs-nestedSortable-no-nesting',
			errorClass: 'mjs-nestedSortable-error',
			listType: 'ol',
			maxLevels: 0,
			protectRoot: false,
			rootID: null,
			rtl: false,
			isAllowed: function(item, parent) { return true; }
		},

		_create: function() {
			this.element.data('sortable', this.element.data('nestedSortable'));

			if (!this.element.is(this.options.listType))
				throw new Error('nestedSortable: Please check the listType option is set to your actual list type');

			return $.ui.sortable.prototype._create.apply(this, arguments);
		},

		destroy: function() {
			this.element
				.removeData("nestedSortable")
				.unbind(".nestedSortable");
			return $.ui.sortable.prototype.destroy.apply(this, arguments);
		},

		_mouseDrag: function(event) {

			//Compute the helpers position
			this.position = this._generatePosition(event);
			this.positionAbs = this._convertPositionTo("absolute");

			if (!this.lastPositionAbs) {
				this.lastPositionAbs = this.positionAbs;
			}

			//Do scrolling
			if(this.options.scroll) {
				var o = this.options, scrolled = false;
				if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {

					if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
						this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
					else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
						this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;

					if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
						this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
					else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
						this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;

				} else {

					if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
						scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
					else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
						scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);

					if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
						scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
					else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
						scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);

				}

				if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
					$.ui.ddmanager.prepareOffsets(this, event);
			}

			//Regenerate the absolute position used for position checks
			this.positionAbs = this._convertPositionTo("absolute");

      // Find the top offset before rearrangement,
      var previousTopOffset = this.placeholder.offset().top;

			//Set the helper position
			if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
			if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';

			//Rearrange
			for (var i = this.items.length - 1; i >= 0; i--) {

				//Cache variables and intersection, continue if no intersection
				var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
				if (!intersection) continue;

				if(itemElement != this.currentItem[0] //cannot intersect with itself
					&&	this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
					&&	!$.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
					&& (this.options.type == 'semi-dynamic' ? !$.contains(this.element[0], itemElement) : true)
					//&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
				) {

					$(itemElement).mouseenter();

					this.direction = intersection == 1 ? "down" : "up";

					if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
						$(itemElement).mouseleave();
						this._rearrange(event, item);
					} else {
						break;
					}

					// Clear emtpy ul's/ol's
					this._clearEmpty(itemElement);

					this._trigger("change", event, this._uiHash());
					break;
				}
			}

			var parentItem = (this.placeholder[0].parentNode.parentNode &&
							 $(this.placeholder[0].parentNode.parentNode).closest('.ui-sortable').length)
				       			? $(this.placeholder[0].parentNode.parentNode)
				       			: null,
			    level = this._getLevel(this.placeholder),
			    childLevels = this._getChildLevels(this.helper);

      // To find the previous sibling in the list, keep backtracking until we hit a valid list item.
			var previousItem = this.placeholder[0].previousSibling ? $(this.placeholder[0].previousSibling) : null;
			if (previousItem != null) {
				while (previousItem[0].nodeName.toLowerCase() != 'li' || previousItem[0] == this.currentItem[0] || previousItem[0] == this.helper[0]) {
					if (previousItem[0].previousSibling) {
						previousItem = $(previousItem[0].previousSibling);
					} else {
						previousItem = null;
						break;
					}
				}
			}

      // To find the next sibling in the list, keep stepping forward until we hit a valid list item.
      var nextItem = this.placeholder[0].nextSibling ? $(this.placeholder[0].nextSibling) : null;
      if (nextItem != null) {
        while (nextItem[0].nodeName.toLowerCase() != 'li' || nextItem[0] == this.currentItem[0] || nextItem[0] == this.helper[0]) {
          if (nextItem[0].nextSibling) {
            nextItem = $(nextItem[0].nextSibling);
          } else {
            nextItem = null;
            break;
          }
        }
      }

			var newList = document.createElement(o.listType);

			this.beyondMaxLevels = 0;

			// If the item is moved to the left, send it to its parent's level unless there are siblings below it.
			if (parentItem != null && nextItem == null &&
					(o.rtl && (this.positionAbs.left + this.helper.outerWidth() > parentItem.offset().left + parentItem.outerWidth()) ||
					!o.rtl && (this.positionAbs.left < parentItem.offset().left))) {
				parentItem.after(this.placeholder[0]);
				this._clearEmpty(parentItem[0]);
				this._trigger("change", event, this._uiHash());
			}
			// If the item is below a sibling and is moved to the right, make it a child of that sibling.
			else if (previousItem != null &&
						(o.rtl && (this.positionAbs.left + this.helper.outerWidth() < previousItem.offset().left + previousItem.outerWidth() - o.tabSize) ||
						!o.rtl && (this.positionAbs.left > previousItem.offset().left + o.tabSize))) {
				this._isAllowed(previousItem, level, level+childLevels+1);
				if (!previousItem.children(o.listType).length) {
					previousItem[0].appendChild(newList);
				}
        // If this item is being moved from the top, add it to the top of the list.
        if (previousTopOffset && (previousTopOffset <= previousItem.offset().top)) {
          previousItem.children(o.listType).prepend(this.placeholder);
        }
        // Otherwise, add it to the bottom of the list.
        else {
				  previousItem.children(o.listType)[0].appendChild(this.placeholder[0]);
        }
				this._trigger("change", event, this._uiHash());
			}
			else {
				this._isAllowed(parentItem, level, level+childLevels);
			}

			//Post events to containers
			this._contactContainers(event);

			//Interconnect with droppables
			if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);

			//Call callbacks
			this._trigger('sort', event, this._uiHash());

			this.lastPositionAbs = this.positionAbs;
			return false;

		},

		_mouseStop: function(event, noPropagation) {

			// If the item is in a position not allowed, send it back
			if (this.beyondMaxLevels) {

				this.placeholder.removeClass(this.options.errorClass);

				if (this.domPosition.prev) {
					$(this.domPosition.prev).after(this.placeholder);
				} else {
					$(this.domPosition.parent).prepend(this.placeholder);
				}

				this._trigger("revert", event, this._uiHash());

			}

			// Clean last empty ul/ol
			for (var i = this.items.length - 1; i >= 0; i--) {
				var item = this.items[i].item[0];
				this._clearEmpty(item);
			}

			$.ui.sortable.prototype._mouseStop.apply(this, arguments);

		},

		serialize: function(options) {

			var o = $.extend({}, this.options, options),
				items = this._getItemsAsjQuery(o && o.connected),
			    str = [];

			$(items).each(function() {
				var res = ($(o.item || this).attr(o.attribute || 'id') || '')
						.match(o.expression || (/(.+)[-=_](.+)/)),
				    pid = ($(o.item || this).parent(o.listType)
						.parent(o.items)
						.attr(o.attribute || 'id') || '')
						.match(o.expression || (/(.+)[-=_](.+)/));

				if (res) {
					str.push(((o.key || res[1]) + '[' + (o.key && o.expression ? res[1] : res[2]) + ']')
						+ '='
						+ (pid ? (o.key && o.expression ? pid[1] : pid[2]) : o.rootID));
				}
			});

			if(!str.length && o.key) {
				str.push(o.key + '=');
			}

			return str.join('&');

		},

		toHierarchy: function(options) {

			var o = $.extend({}, this.options, options),
				sDepth = o.startDepthCount || 0,
			    ret = [];

			$(this.element).children(o.items).each(function () {
				var level = _recursiveItems(this);
				ret.push(level);
			});

			return ret;

			function _recursiveItems(item) {
				var id = ($(item).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
				if (id) {
					var currentItem = {"id" : id[2]};
					if ($(item).children(o.listType).children(o.items).length > 0) {
						currentItem.children = [];
						$(item).children(o.listType).children(o.items).each(function() {
							var level = _recursiveItems(this);
							currentItem.children.push(level);
						});
					}
					return currentItem;
				}
			}
		},

		toArray: function(options) {

			var o = $.extend({}, this.options, options),
				sDepth = o.startDepthCount || 0,
			    ret = [],
			    left = 2;

			ret.push({
				"item_id": o.rootID,
				"parent_id": 'none',
				"depth": sDepth,
				"left": '1',
				"right": ($(o.items, this.element).length + 1) * 2
			});

			$(this.element).children(o.items).each(function () {
				left = _recursiveArray(this, sDepth + 1, left);
			});

			ret = ret.sort(function(a,b){ return (a.left - b.left); });

			return ret;

			function _recursiveArray(item, depth, left) {

				var right = left + 1,
				    id,
				    pid;

				if ($(item).children(o.listType).children(o.items).length > 0) {
					depth ++;
					$(item).children(o.listType).children(o.items).each(function () {
						right = _recursiveArray($(this), depth, right);
					});
					depth --;
				}

				id = ($(item).attr(o.attribute || 'id')).match(o.expression || (/(.+)[-=_](.+)/));

				if (depth === sDepth + 1) {
					pid = o.rootID;
				} else {
					var parentItem = ($(item).parent(o.listType)
											 .parent(o.items)
											 .attr(o.attribute || 'id'))
											 .match(o.expression || (/(.+)[-=_](.+)/));
					pid = parentItem[2];
				}

				if (id) {
						ret.push({"item_id": id[2], "parent_id": pid, "depth": depth, "left": left, "right": right});
				}

				left = right + 1;
				return left;
			}

		},

		_clearEmpty: function(item) {

			var emptyList = $(item).children(this.options.listType);
			if (emptyList.length && !emptyList.children().length) {
				emptyList.remove();
			}

		},

		_getLevel: function(item) {

			var level = 1;

			if (this.options.listType) {
				var list = item.closest(this.options.listType);
				while (list && list.length > 0 &&
                    	!list.is('.ui-sortable')) {
					level++;
					list = list.parent().closest(this.options.listType);
				}
			}

			return level;
		},

		_getChildLevels: function(parent, depth) {
			var self = this,
			    o = this.options,
			    result = 0;
			depth = depth || 0;

			$(parent).children(o.listType).children(o.items).each(function (index, child) {
					result = Math.max(self._getChildLevels(child, depth + 1), result);
			});

			return depth ? result + 1 : result;
		},

		_isAllowed: function(parentItem, level, levels) {
			var o = this.options,
				isRoot = $(this.domPosition.parent).hasClass('ui-sortable') ? true : false,
				maxLevels = this.placeholder.closest('.ui-sortable').nestedSortable('option', 'maxLevels'); // this takes into account the maxLevels set to the recipient list

			// Is the root protected?
			// Are we trying to nest under a no-nest?
			// Are we nesting too deep?
			if (!o.isAllowed(parentItem, this.placeholder) ||
				parentItem && parentItem.hasClass(o.disableNesting) ||
				o.protectRoot && (parentItem == null && !isRoot || isRoot && level > 1)) {
					this.placeholder.addClass(o.errorClass);
					if (maxLevels < levels && maxLevels != 0) {
						this.beyondMaxLevels = levels - maxLevels;
					} else {
						this.beyondMaxLevels = 1;
					}
			} else {
				if (maxLevels < levels && maxLevels != 0) {
					this.placeholder.addClass(o.errorClass);
					this.beyondMaxLevels = levels - maxLevels;
				} else {
					this.placeholder.removeClass(o.errorClass);
					this.beyondMaxLevels = 0;
				}
			}
		}

	}));

	$.mjs.nestedSortable.prototype.options = $.extend({}, $.ui.sortable.prototype.options, $.mjs.nestedSortable.prototype.options);
})(jQuery);